#include <stdio.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define INIT_SIZE 20
#define INCREMENT_SIZE 5

typedef int SElemType;
typedef int Status;

//存储结构
typedef struct {
    SElemType *base;    //栈尾指针
    SElemType *top;     //栈顶的指针
    int size;           //栈大小
} SqStack;

//初始化栈
Status InitStack(SqStack *s) {
    s->base = (SElemType *)malloc(INIT_SIZE * sizeof(SElemType)); 
    if (!s->base) {
        exit(OVERFLOW);
    }
    //设置栈顶指针初始化位置在栈尾上以及栈大小
    s->top = s->base;
    s->size = INIT_SIZE;
    return OK;
}

//销毁栈
Status DestroyStack(SqStack *s) {
    //先释放栈顶指针
    free(s->base);
    s->base = NULL;
    s->top = NULL;
    s->size = 0;
    return OK;
}

//清空栈
Status ClearStack(SqStack *s) {
    //等待栈顶指针指向了栈尾
    s->top = s->base;
    return OK;
}

//判定栈是否空
Status IsEmpty(SqStack s) {
    if (s.top == NULL) {
        return TRUE;
    } else {
        return FALSE;
    }
}

//获取栈的长度
int GetLength(SqStack s) {
    return s.top - s.base;
}

//获取栈元素
Status GetTop(SqStack s, SElemType *e) {
    if (s.top > s.base) {
        //判定栈是否空
        *e = *(--s.top);
        return OK;
    } else {
        return ERROR;
    }
}

//压栈
//判定是否满栈，若出错则重新分配空间
Status Push(SqStack *s, SElemType e) {
    if ((s->top - s->base) / sizeof(SElemType) >= s->size) {
        //判定栈是否还有空间
        s->base = (SElemType *)realloc(s->base, (s->size + INCREMENT_SIZE) * sizeof(SElemType));
        if (!s->base) {
            exit(OVERFLOW);
        }
        s->top = s->base + s->size;
        s->size += INCREMENT_SIZE;
    }
    *s->top = e;
    s->top++;
    return OK;
}

//出栈
//判定是否满栈，若空则报错，获取栈顶元素e，栈顶指针-1
Status Pop(SqStack *S, SElemType *e){
    if (S->top == S->base){
        return ERROR;
    }
    S->top--; // 栈顶指针往下移
    *e = *S->top;
    return OK;
}

//访问某个元素
void visit(SElemType e) {
    printf("element = %d \n", e);
}

//遍历栈
Status TraverseStack(SqStack s, void (*visit)(SElemType)) {
    while (s.top > s.base) {
        visit(*s.base);
        s.base++;
    }
    return OK;
}

int main() {
    SqStack S;
    if (InitStack(&S)){
        SElemType e;
        int i;

        printf("Init_Success!\n");

        if (IsEmpty(S)){
            printf("Stack is empty\n");
        }

        for (i = 0; i < 10; i++){
            Push(&S, i);
        }

        GetTop(S, &e);
        printf("The first element is %d\n", e);

        printf("length is %d\n", GetLength(S));

        Pop(&S, &e);
        printf("Pop element is %d\n", e);

        TraverseStack(S, *visit);

        if (DestroyStack(&S)){
            printf("\ndestroy_success\n");
        }
    }
}